package com.madao.im.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

/**
 * bean 配置
 *
 * @author chengjunchao
 * @version 1.0.0
 * @date 2021/12/6 15:28
 */
@Slf4j
@Configuration
public class BeanConfig {
    @Value("${httpclient.ReadTimeout:15000}")
    private Integer readTimeout;
    @Value("${httpclient.ConnectTimeout:10000}")
    private Integer connectTimeout;

    private static CloseableHttpClient acceptsUntrustedCertsHttpClient()
            throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        // 重试次数，默认是3次，没有开启
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true));
        // 保持长连接配置，需要在头添加Keep-Alive
        httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());

        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
        httpClientBuilder.setSSLContext(sslContext);

        List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537" +
                        ".36"));
        headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
        headers.add(new BasicHeader("Accept-Language", "zh-CN"));
        headers.add(new BasicHeader("Connection", "Keep-Alive"));

        httpClientBuilder.setDefaultHeaders(headers);

        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory)
                .build();

        PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connMgr.setMaxTotal(200);
        connMgr.setDefaultMaxPerRoute(100);
        httpClientBuilder.setConnectionManager(connMgr);

        return httpClientBuilder.build();
    }

    private RestTemplate getRestTemplate() {
        RestTemplate restTemplate = null;
        try {
            CloseableHttpClient httpClient = acceptsUntrustedCertsHttpClient();
            HttpComponentsClientHttpRequestFactory httpClientFactory = new HttpComponentsClientHttpRequestFactory();
            httpClientFactory.setHttpClient(httpClient);
            httpClientFactory.setConnectionRequestTimeout(60 * 1000);
            httpClientFactory.setReadTimeout(readTimeout);
            httpClientFactory.setConnectTimeout(connectTimeout);
            restTemplate = new RestTemplate(httpClientFactory);

            // 使用 utf-8 编码集的 conver 替换默认的 conver（默认的 string conver
            // 的编码集为"ISO-8859-1"）
            List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
            messageConverters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
            messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        } catch (Exception e) {
            log.error(" restTemplate配置异常:{}", e);
        }
        return restTemplate;
    }

    @Bean
    public AuthorizeFilter getAuthorizeFilter() {
        return new AuthorizeFilter();
    }

    /**
     * 登录拦截
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean getWebApiFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        //登录过滤器
        registrationBean.setFilter(getAuthorizeFilter());
        List<String> urlPatterns = new ArrayList<>();
        //拦截路径，可以添加多个
        urlPatterns.add("/*");
        registrationBean.setUrlPatterns(urlPatterns);
        registrationBean.setOrder(1);
        return registrationBean;
    }

    /**
     * restTemplate配置
     *
     * @return
     */
    @Bean
    public RestTemplate restTemplate() {
        return getRestTemplate();
    }
}
